{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8382962d",
   "metadata": {},
   "source": [
    "# 7-1，推荐算法业务入门\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e60b65e0",
   "metadata": {},
   "source": [
    "## 一， 搜索和推荐\n",
    "\n",
    "搜索是人找物，而推荐是物找人。搜索一般用来满足用户比较明确的需求，而推荐则可以用来满足用户相对模糊的需求。\n",
    "\n",
    "大家熟悉的推荐系统包括 抖音短视频、今日头条新闻推荐、网易云音乐每日推荐、淘宝京东的猜你喜欢推荐、B站的视频推荐等等。\n",
    "\n",
    "大家熟悉的搜索系统包括 谷歌百度搜索、淘宝京东的商品搜索栏、知乎问题搜索栏、以及脉脉上的找人搜索等等。\n",
    "\n",
    "搜索有一定的使用门槛，用户需要输入关键词，至少要会打字吧，并相对准确地描述自己的兴趣。\n",
    "\n",
    "但推荐几乎没有使用门槛，用户只要会刷新就可以了，每次刷新都会出来新的东西。\n",
    "\n",
    "\n",
    "完成一个最简单的推荐系统的方法就是每次请求都保证能出新的东西，也就是随机不重复推荐。\n",
    "\n",
    "但搜索不能这么简单，你一定出来的要是和输入相关的东西，不然就不叫搜索了。\n",
    "\n",
    "一个较理想的推荐系统可以做到**千人千面**，根据用户偏好个性化地进行推荐。\n",
    "\n",
    "\n",
    "\n",
    "## 二， 推荐系统的价值\n",
    "\n",
    "推荐系统是连接生产者和消费者的中间媒介。它对于生产者、消费者、以及平台都有各自的价值。\n",
    "\n",
    "以抖音短视频为例，生产者指的是视频创者，消费者是刷视频的用户，平台指的是抖音公司团队。\n",
    "\n",
    "\n",
    "* 对消费者：帮助消费者便捷地获取信息。\n",
    "\n",
    "* 对生产者：帮助生产者获取流量曝光和用户增长。\n",
    "\n",
    "* 对平台：平台可以通过卖广告赚取收益。\n",
    "\n",
    "\n",
    "一般来说说，用户使用时长越长，平台就可以插入更多的广告。所以，推荐系统常常以用户使用时常为核心优化指标。\n",
    "\n",
    "![](https://tva1.sinaimg.cn/large/e6c9d24egy1h4gzw2yn6fj20jk0fzwgu.jpg)\n",
    "\n",
    "\n",
    "\n",
    "对于生产者，推荐系统非常重要的一点特性是要具备**长尾效应**，即头部的作者能获得主要的曝光，但中小创作者也必须要能够获得一定的流量。\n",
    "\n",
    "否则大部分的作者创作积极性被打压掉之后，平台会慢慢死掉。\n",
    "\n",
    "我们可以看到发展比较好的推荐系统的长尾都做的非常好，像抖音、B站、快手，捧红了非常多的草根创作者。\n",
    "\n",
    "这一点是非常重要的。\n",
    "\n",
    "![](https://tva1.sinaimg.cn/large/e6c9d24egy1h4l5apverfj20rs0eg74g.jpg)\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12e17447",
   "metadata": {},
   "source": [
    "## 三， 推荐系统架构\n",
    "\n",
    "如何来搭建一个推荐系统呢？\n",
    "\n",
    "第一步，我们得知道有哪些东西可以推荐吧。这就需要一个索引池，里面存储了可能被推荐的全量内容的id以及它们的一些特征。对于有些有时效性的内容，比如新闻，我们在其时间过期之后，要从索引池中拿掉。同时，通过审核与控制索引池中的内容，我们可以确保不犯致命错误，不推荐涉黄涉非的内容给用户。\n",
    "\n",
    "第二步，当用户通过登录APP或者刷新操作触发了一个获取推荐信息的请求的时候，我们得知道这个用户当前有啥喜好吧。这就需要一个特征服务，获取用户的年龄性别地域等属性特征，以及根据用户之前的浏览点赞等记录计算的行为特征，由于用户的喜好可能变化较快且需求较高，我们需要搭建服务以保证高性能。\n",
    "\n",
    "\n",
    "第三步，我们得确定把索引池中哪个内容或者哪些内容推荐给用户吧。这就需要一个排序模块，其目的是将索引池中所有内容按照用户可能的喜好程度进行排序。如果索引池非常大，排序模块通常会进一步分成 召回和排序两个阶段，有些推荐系统还会在它们中间加上一个粗排阶段。此外，排序模块中通常还会使用一些打压保送重排的策略来对模型预测结果进行一些人为干预。\n",
    "\n",
    "\n",
    "第四步，现在我们已经确定把哪些内容推荐给用户了，那赶紧推吧! 且慢，我们还有一个展示逻辑。许多时候我们最终呈现给用户的是图文的混排，或者内容和广告的混排，这个时候需要设计适当的展示逻辑给到前端。\n",
    "\n",
    "\n",
    "Congratulations! 经过 物料索引，特征服务，排序模块，展示逻辑 这样4步，我们终于成功地把东西推给用户了。现在我们是不是就可以收工，坐等数钱就行了呢？Too young too Naive, 还有无穷无尽的监控和迭代呀。\n",
    "\n",
    "第五步，为了监控我们的推荐是否有效，我们需要搭建日志系统，记录推送前后一切信息。这些信息包括推送前获取的特征、模型的排序结果 以及 推送后用户的行为反馈。通过对比排序结果和用户反馈我们可以计算点击率以及浏览时长评估指标，并且形成新的训练数据来让排序模块继续训练。\n",
    "\n",
    "\n",
    "第六步，为了进一步迭代优化我们的推荐系统，我们需要做AB测试实验，并分析实验结果，这就需要一个分析系统，分析系统基于日志系统的数据。AB测试一般把用户随机进行划分为对照组(A组,不添加改进点)和实验组(B组,添加改进点)，通过对比AB之间的差异，来展示我们所加的改进点是否有效。推荐系统的迭代一般是这么个流程，设计改进idea->做线下实验->上AB试试->有效就推广到全量。\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0914ae89",
   "metadata": {},
   "source": [
    "![](https://tva1.sinaimg.cn/large/e6c9d24egy1h4oo37b5hjj20k00ekmxf.jpg)\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "912419b6",
   "metadata": {},
   "source": [
    "## 四， 召回粗排精排\n",
    "\n",
    "推荐系统架构中的排序模块，一般会分成 召回、粗排、精排三个阶段。这几个阶段，可以比喻成索引库全部item争夺最终展示机会的初赛，复赛 和 决赛。\n",
    "\n",
    "召回(recall)就好像是初赛，比较简单，效率优先。\n",
    "\n",
    "一开始我们的索引库中可能有数万数十万的item，这些item都是有资格被展示的，如果我们直接上复杂模型对这么多item进行排序，性能是很差的。所以我们可以先设计方法简单性能高效(例如双塔模型,LR,FM以及各种规则策略)的召回模块来挖掘出原则上任何用户有可能感兴趣的东西，召回的输出一般在几千这样的量级。为什么这个环节叫做召回呢，因为这个环节不在乎你把多少错误的东西放进来，但是非常在乎你没有把对的东西放进来(漏召回)。\n",
    "\n",
    "实践中，召回一般都会做多路召回策略。第一种召回，是非个性化的。比如对于新用户，我们要确保用最高质量的视频把他们留住，那么我们可以划一个\"精品池\"出来，作为一路召回。第二种召回，是i2i，即item-to-item。根据用户的历史item，来找相似的item。比如说我们把用户过去点过赞的视频拿出来，去找画面上，BGM上，或者用户行为结构上相似的视频。第三种召回是u2i，即纯粹从user和item的关系出发。双塔就是一个典型的u2i。在用户请求过来的时候，计算出user的embedding，然后去一个事先存好的item embedding的空间，寻找最相似的一批拿出来。由于要实时计算user特征，它的负担要大于前面两者，但这种召回个性化程度最高，一般会作为主路召回。\n",
    "\n",
    "粗排(pre-rank)就好像是复赛，中等难度，平衡精效。\n",
    "\n",
    "召回的输出有数千，直接上精排的话可能还是比较慢，我们可以使用一些中等复杂的模型(例如MLP,DeepFM) 对召回输出的几千个item进行初步的排序，输出几百个到最终的精排环节。起到在召回和精排之间进行精度和效率的平衡。粗排环节不是必须的，如果索引库中的候选的item数量很少，甚至召回环节也可不要。\n",
    "\n",
    "精排(rank)就好像是决赛，疯狂难度，精度优先。\n",
    "\n",
    "精排是最纯粹的排序，也是最纯粹的机器学习模块。它的目标只有一个，就是根据手头所有的信息输出最准的预测。精排的输入只有几百个，模型就可以非常复杂(例如DCN啊, 各种序列模型DIEN啊, 什么Transformer啊, 什么MMOE啊)，是一个纯粹的追求模型精度的环节。这个环节也是学术界各种相关的论文paper研究得最多的部分。\n",
    "\n",
    "\n",
    "召回->粗排->精排 实际上是计算压力从大到小，模型复杂度从小到大的一个过程。\n",
    "\n",
    "\n",
    "\n",
    "![](https://tva1.sinaimg.cn/large/e6c9d24egy1h4p0jmhhv0j20k10bvq37.jpg)\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3faf669e",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "## 五， 打压保送重排\n",
    "\n",
    "在模型之外，在推荐的整个过程中还穿插着许多策略(规则)环节来辅助。\n",
    "\n",
    "这些策略有些是为了推荐的结果更好，有些则是为了某种长期规划或者营利诉求。\n",
    "\n",
    "推荐系统中常用到的一些策略包括以下三种。\n",
    "\n",
    "1，打压。 有政策风险或者与平台风格不符合的内容需要打压。\n",
    "\n",
    "2，保送。 常见的是营收原因(金主爸爸掏钱了)需要保送。此外，对于新内容，常常有一定的保送流量，以确保长尾效应，维持平台活力。\n",
    "\n",
    "3，重排。 重排一是确保最终推荐内容的多样性，二是防止重复推荐用户最近浏览过的内容。\n",
    "\n",
    "\n",
    "![](https://tva1.sinaimg.cn/large/e6c9d24egy1h4p0ep9egqj20k00e6gm5.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b6d50ad",
   "metadata": {},
   "source": [
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4074543d",
   "metadata": {},
   "source": [
    "## 六， 推荐系统的局限性\n",
    "\n",
    "尽管各个推荐系统平台都把自己的模型和算法吹得天花乱坠，但实际上模型和算法对于推荐系统的成功的贡献是有限的，并且具有它的局限性。\n",
    "\n",
    "主要体现在以下几点。\n",
    "\n",
    "1，优质内容是根本。没有足够多用户喜爱的优质内容，推荐系统的模型算法再厉害也是无用武之地的。如果内容足够优质，非常简单的推荐算法就能够起到很好的效果。\n",
    "\n",
    "2，存在用户信息茧房。推荐系统存在着过分迎合用户偏好的倾向，让用户沉浸在一些短期的感觉刺激中浪费许多时间，这对用户的长期价值可能是负的。\n",
    "\n",
    "3，模型自己学自己。推荐系统的模型学习的数据是有偏的，都是曾经被模型选中的样本才有可能受到用户点赞喜欢获得正反馈成为正样本。虽然大部分推荐系统对新内容都有一些随机流量，但绝大部分样本都没有足够多的流量来进行评估。可能相同的内容换个id重新再发一遍就能获得多得多的流量，这里面存在着很大的随机性。\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f5784f03",
   "metadata": {},
   "source": [
    "本文主要参考知乎@水哥的《从零单排推荐系统》系列专栏博客，根据个人理解进行了一些概要整理，特此感谢。\n",
    "\n",
    "https://zhuanlan.zhihu.com/p/407871839\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f904195e",
   "metadata": {},
   "source": [
    "**如果本书对你有所帮助，想鼓励一下作者，记得给本项目加一颗星星star⭐️，并分享给你的朋友们喔😊!** \n",
    "\n",
    "如果对本书内容理解上有需要进一步和作者交流的地方，欢迎在公众号\"算法美食屋\"下留言。作者时间和精力有限，会酌情予以回复。\n",
    "\n",
    "也可以在公众号后台回复关键字：**加群**，加入读者交流群和大家讨论。\n",
    "\n",
    "![算法美食屋logo.png](https://tva1.sinaimg.cn/large/e6c9d24egy1h41m2zugguj20k00b9q46.jpg)"
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "formats": "ipynb,md",
   "main_language": "python"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
